/*
 * ADC.c
 *
 * Created: 1/17/2013 7:03:38 PM
 *  Author: Hp-Minion
 */ 
/*****************************************************************************************/
#include <avr/io.h>
#include "General.h"
#include "Port.h"
#include "ADC.h"
#include "USART_0.h"
/*****************************************************************************************/
void ADC_SelectChannel( unsigned char pin )
{
	if (( pin >= 0 ) && ( pin <= 7 ))
	{
		/* Clean the Register and select the new channel */
		ADMUX &= 0xF0;
        ADMUX |= pin;
	}		
}
/*****************************************************************************************/
void ADC_Init(unsigned char pin)
{
	PinMode(pin,'A',INPUT);
	/* Enable ADC channels */
	ADC_SelectChannel( pin );
	/* Enable AREF */
	ADMUX |= (1<<REFS0);
	/* Enable ADC with 128 pre-scaler */
	ADCSRA |= (1<<ADEN) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);
}
/*****************************************************************************************/
void ADC_Start(void)
{
	/* Start conversion */
	ADCSRA |= (1<<ADSC);
	/* Wait until the conversion is finished */
	while(ADCSRA & (1<<ADSC));
}
/*****************************************************************************************/
unsigned short ADC_Reading(void)
{
	unsigned short L_reg = 0;
	unsigned short H_reg = 0;
	
	L_reg = ADCL;
	H_reg = ADCH;
	
	return (H_reg << 8) | L_reg;
}
/*****************************************************************************************/
float ADC_GetVlots(unsigned short adcValue)
{
	return (float)(adcValue * (float)AREF_VALUE)/1023.0;
}
/*****************************************************************************************/
 unsigned short getAverage( unsigned short inValue[MAX_ADC_READINGS], unsigned short size)
{
	unsigned long sum = 0;
	unsigned short i = 0;
	
	for (i = 0; i < size; i++)
    {
        sum += inValue[i];
    }

    return (unsigned short)sum / size;
}
/*****************************************************************************************/
unsigned char getPercentage( unsigned short inValue)
{
	return (unsigned char)((inValue * 100)/(MAX_DECIMAL_RESOLUTION - 1)); 
}
/*****************************************************************************************/
StatusCodes ADC_Temp_Handler( unsigned char intPin, AreaConditions *garden )
{
	StatusCodes status = STATUS_CODE_UNDEFINED;
	unsigned char i = 0;
	unsigned short ADC_read[MAX_ADC_READINGS] = { 0 };
	static unsigned short ADC_val = 0;
    static float ADC_Vin = 0;
    static unsigned short Temp_K = 0;
    static short Temp_C = 0;
	
	/* Initialize ADC channel */
	ADC_Init(intPin);
	
	/* Get MAX_ADC_READINGS # of ADC values */
    for (i=0; i<MAX_ADC_READINGS; i++)
	{
		ADC_Start();
	    ADC_read[i] = ADC_Reading();
		
#       ifdef DEBUG_LVL_2
        PRINT_u8("\n ADC=%i C", ADC_read[i]);
#       endif
	}
	/* Save the average of the ADC values taken */
	ADC_val = getAverage(ADC_read, MAX_ADC_READINGS);
	
#   ifdef DEBUG_LVL_1
    PRINT_u8("\n Avrg=%i C", ADC_val);
#   endif
	
	/* Find out the voltage value of the Sensor */
	ADC_Vin = ADC_GetVlots(ADC_val);
	
	/* Compute the temperature knowing 10mV are 1 grade Kelvin */
	Temp_K = (unsigned short)(ADC_Vin * 100);
	Temp_C = Temp_K - KELVIN_OVER_CELSIUS_OFFSET;
	
#   ifdef DEBUG_LVL_0
    PRINT_u8("\n SoilT: %i C", Temp_C);
#   endif

    /* Return Soil temperature */
	garden->temperature = Temp_C;
	status = STATUS_CODE_SUCCESS;
	
	return status;
}
/*****************************************************************************************/
StatusCodes ADC_Hum_Handler( unsigned char intPin, AreaConditions *garden )
{
	StatusCodes status = STATUS_CODE_UNDEFINED;
	unsigned char i = 0;
	unsigned short ADC_read[MAX_ADC_READINGS] = { 0 };
	static unsigned short ADC_val = 0;
	static unsigned char ADC_Result = 0;
	
	/* Initialize ADC channel */
	ADC_Init(intPin);
	
	/* Get MAX_ADC_READINGS # of ADC values */
    for (i=0; i<MAX_ADC_READINGS; i++)
	{
		ADC_Start();
	    ADC_read[i] = ADC_Reading();
		
#       ifdef DEBUG_LVL_2
        PRINT_u8("\n ADC=%i W", ADC_read[i]);
#       endif
	}
	
	/* Save the average of the ADC values taken */
	ADC_val = getAverage(ADC_read, MAX_ADC_READINGS);
	
#   ifdef DEBUG_LVL_1
    PRINT_u8("\n Avrg=%i", ADC_val;
#   endif
    
	///* Check for extreme result */
	//if (ADC_val == 0)
	//{
		//status = STATUS_CODE_FAIL;
	//}
	
	/* Compute humidity percent % */
	ADC_Result = getPercentage(ADC_val);
	
#   ifdef DEBUG_LVL_0
	PRINT_u8("\n SoilH: %i %%", ADC_Result);
#   endif

	/* Compute the humidity knowing:
	   Humidity sensor
                0 Air
          1 - 200 Dry Soil
		200 - 450 Normal Soil
        450 - 700 Wet Soil
        700 - 950 Water
	*/
	//if( ADC_val == 0)
	//{
		//soilHumResult = SOIL_HUM_TYPE_AIR;
	//}
	//else if( ADC_val <= SOIL_HUM_STEP_DRY )
	//{
		//soilHumResult = SOIL_HUM_TYPE_DRY;
	//}
	//else if( ADC_val <= SOIL_HUM_STEP_NORMAL )
	//{
		//soilHumResult = SOIL_HUM_TYPE_NORMAL;
	//}
	//else if( ADC_val <= SOIL_HUM_STEP_WET )
	//{
		//soilHumResult = SOIL_HUM_TYPE_WET;
	//} 
	//else
	//{
		//soilHumResult = SOIL_HUM_TYPE_WATER;
	//}
	
	
	/* Return Soil humidity % */
	garden->humidity = ADC_Result;
	status = STATUS_CODE_SUCCESS;
	
    return status;	
}
/*****************************************************************************************/
StatusCodes ADC_Light_Handler( unsigned char intPin, unsigned char *gardenLight )
{
	StatusCodes status = STATUS_CODE_UNDEFINED;
	unsigned char i = 0;
	unsigned short ADC_read[MAX_ADC_READINGS] = { 0 };
	static unsigned short ADC_val = 0;
	static unsigned char ADC_Result = 0;
	
	/* Initialize ADC channel */
	ADC_Init(intPin);
	
	/* Get MAX_ADC_READINGS # of ADC values */
    for (i=0; i<MAX_ADC_READINGS; i++)
	{
		ADC_Start();
	    ADC_read[i] = ADC_Reading();
		
#       ifdef DEBUG_LVL_2
        PRINT_u8("\n ADC=%i lx", ADC_read[i]);
#       endif
	}
	
	/* Save the average of the ADC values taken */
	ADC_val = getAverage(ADC_read, MAX_ADC_READINGS);
	
#   ifdef DEBUG_LVL_1
    PRINT_u8("\n Avrg=%i", ADC_val);
#   endif
	
	/* Compute light percent % */
	ADC_Result = getPercentage(ADC_val);
	
#   ifdef DEBUG_LVL_0
    PRINT_u8("\n Light: %i %%", ADC_Result);
#   endif

    /* Return Light value % */
	*gardenLight = ADC_Result;
	status = STATUS_CODE_SUCCESS;
	
    return status;	
}
/*****************************************************************************************/